///数据类型


/*数据类型:
整数类型：
    无符号整数：u开头 u8, u16, u32, u64, u128
    有符号整数: i开头, i8, i16, i32, i64, i128

    arch: 由计算机的系统架构决定
        isize: 32位计算机，i32类型； 64位计算机,i64类型;
        usize: 32位计算机，u32类型； 64位计算机,u64类型;

    整数的字面值(写法):
    10进制(Decimal) : 90_90       可以加下划线增加可读性
    16进制(Hex):      0xff        0x开头
    8进制(Octal):     0o77        0o开头
    2进制(Binary):    0b1111_0000 0b开头
    字节类型(u8):      b'A'

    不声明类型，默认i32类型;

浮点类型:
    f32, 32位 单精度
    f64, 64位 双精度 (默认)

布尔类型:
    true,false;

字符型(char):
    描述单个字符，占4个字节，是unicode的标量值，可以表示比ascii码更多的字符内容。
    unicode范围：
        u+0000 ~ u+d7ff
        u+e000 ~ u+10ffff

字符串类型：最底层的是不定长类型str，更常用的是字符串切片&str和堆分配字符串String， 其中字符串切片是静态分配的，
        有固定的大小，并且不可变，而堆分配字符串是可变的.

切片：引用一个数组的部分数据并且不需要拷贝，可表示为&[T]。

复合类型：
    元组(tuple): 具有固定大小的有序列表，每个元素都有自己的类型，通过解构或者索引来获得每个元素的值
    数组: 具有固定大小，并且元素都是同种类型，可表示为[T; N]。

指针：最底层的是裸指针*const T和*mut T，但解引用它们是不安全的，必须放到unsafe块里。

函数：具有函数类型的变量实质上是一个函数指针。

元类型：即()，其唯一的值也是()。

有几点是需要特别注意的：

数值类型可以使用_分隔符来增加可读性。
Rust还支持单字节字符b'H'以及单字节字符串b"Hello"，仅限制于ASCII字符。 此外，还可以使用r#"..."#标记来表示原始字符串，不需要对特殊字符进行转义。
使用&符号将String类型转换成&str类型很廉价， 但是使用to_string()方法将&str转换到String类型涉及到分配内存， 除非很有必要否则不要这么做。
数组的长度是不可变的，动态的数组称为Vec (vector)，可以使用宏vec!创建。
元组可以使用==和!=运算符来判断是否相同。
不多于32个元素的数组和不多于12个元素的元组在值传递时是自动复制的。
Rust不提供原生类型之间的隐式转换，只能使用as关键字显式转换。
可以使用type关键字定义某个类型的别名，并且应该采用驼峰命名法。
*/
//常量
const MAX: u32 = 100_00;
/*变量*/
#[test]
pub fn variable(){
    let x: i32= 5; //不可变变量
    println!("x = {}", x);

    let mut y: i32 = 89; //可变变量
    println!("y = {}", y);
    y = 23;
    println!("y = {}", y);

    println!("MAX = {}", MAX);
}
/*Shadowing 隐藏,相同变量名可以重复声明，先声明的会被隐藏*/
pub fn shadowing(){
    let x = 5;
    let x = x + 2;
    println!("x = {}", x);
}
#[test]
pub fn data_type(){
    //字符串转数字，必须指定数据类型
    let guess: u32 = "42".parse().expect("not a num");
    println!("guess = {}", guess);
    //整型
    let i: i8 = 9;
    println!("i = {}", i);
    //浮点类型
    let f: f32 = 45.3;
    println!("f = {}", f);

    let f = 45.3;
    println!("f = {}", f);

    //布尔类型
    let b: bool= true;
    println!("b = {}", b);

    //字符类型
    let x = 'z';
    let y: char = 'Z';

    println!("x ={}, y = {}", x, y);

    let c = b'x'; //单字节字符
    println!("c = {}", c ); //120
    println!("c = {}", c as char ); //x

    //字符串
    let s: String  = String::from("hello中国");
    println!("{}, len = {}", s, s.len()); //len返回的是所占字节数
 
    //字符串切片
    let str_slice = &s[0..4];
    println!("{}", str_slice);


    //元组类型
    let tup : (i32, f64, u8) = (500, 32.5, 8);
    println!("{}, {}, {}", tup.0, tup.1, tup.2);
    let (x, y, z) = tup;
    println!("{}, {}, {}", x, y, z);

    //数组类型
    let month = ["一月", "二月"];
    for i in month {
        print!("{},", i);
    }
    println!();
    //数组 i32类型，长度为10,初始值都是0
    let mut nums:[i32; 10] = [0; 10];
    nums[0] = 10;
    for i in nums {
        print!("{},", i);
    }

    println!();
    let arr:[i32;3] = [1, 3, 34];
    for i in arr {
        print!("{},", i);
    }
    println!();
    let a = [3; 5]; //长度为5， 每个元素都是3
    println!("{:?}", a);

    //切片(引用数组的部分数组，可变引用可以修改原数组的值)
    let nums_slice = &mut nums[0..4];
    println!("{:?}", nums_slice);
    nums_slice[0] = 23;
    println!("{:?}", nums);

    //引用类型
    let mut i = 32;
    let  p = &mut i; //p为i的可变引用
    *p = 22; //通过p修改i的值
    println!("{}", i);

    // raw pointers
    let x = 5;
    let raw = &x as *const i32;
    let points_at = unsafe { *raw };
    println!("{}", points_at); //5

    // functions 函数指针
    fn foo(x: i32) -> i32 { x }
    let bar: fn(i32) -> i32 = foo;
    let r = foo(32);
    println!("{}", r);
}

//元组操作
pub fn tuple_demo(){
    let mut pair = (32, 34);
    println!("{},{}", pair.0, pair.1); //32,34

    let r = &mut pair; //拿到可变引用
    *r = (23, 35); //修改值
    println!("{},{}", pair.0, pair.1); //23,35

    let (ref mut i, ref mut j) = &mut pair; //拿到可变引用
    *i = 40;
    *j = 90;
    println!("{},{}", i, j); //40,90
    println!("{},{}", pair.0, pair.1); //40,90

}
///
pub fn data_type_demo1(){
    println!("data type demo1")
}

#[cfg(test)]
mod tests{
    use crate::basic::basic01_data_type::{data_type_demo1, data_type};

    #[test]
    fn test1(){
       data_type();
    }

}

